use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{self, Instruction, BytecodeReader}, rtda::Frame};

// tableswitch
// <0-3 byte pad>
// defaultbyte1
// defaultbyte2
// defaultbyte3
// defaultbyte4
// lowbyte1
// lowbyte2
// lowbyte3
// lowbyte4
// highbyte1
// highbyte2
// highbyte3
// highbyte4
// jump offsets...

// Access jump table by index and jump
#[derive(Debug, Default)]
pub struct TABLE_SWITCH {
    default_offset: i32, // 指令码后有0-3个字节的填充，default_offset位4的倍数
    low: i32,
    high: i32,
    jump_offsets: Vec<i32> // 对应各个case执行代码跳过的便宜量
}

impl Instruction for TABLE_SWITCH {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        // 跳过填充
        reader.skip_padding();
        self.default_offset = reader.read_i32();
        self.low = reader.read_i32();
        self.high = reader.read_i32();
        let jump_offsets_count = self.high - self.low + 1;
        self.jump_offsets = reader.read_i32s(jump_offsets_count as usize);
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let index = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        let offset = 
            if index >= self.low && index <= self.high { 
                self.jump_offsets[(index - self.low) as usize] 
            } else { 
                self.default_offset 
            };
        base::branch(frame, offset)
    }
}